package com.liuya.base;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liuya.common.*;
import com.liuya.page.Filter;
import com.liuya.page.Pageable;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author liuya
 * @date 20160825
 */
public class BaseMethods<T extends BaseModel> {
    protected Logger logger = LogManager.getLogger();
    @Autowired
    public BaseMapper<T> mapper;

    /**
     * 生成redis用主键
     */
    public String createId(String key) {
        String redisKey = "REDIS_TBL_" + key;
        String dateTime = DateUtil.getDateTime(DateUtil.DATE_PATTERN.YYYYMMDDHHMMSSSSS);
        String str = dateTime + JedisUtil.incr(redisKey);
        return str;
    }

    public void init() {
        List<T> list = mapper.selectAll(null);
        for(BaseModel record:list) {
            JedisUtil.set(getCacheKey(record.getId()), record);
        }
    }

    @Transactional
    public boolean batchSave(Collection coll) {
        int numers = 1;
        for (Iterator iter = coll.iterator(); iter.hasNext(); ) {
            T mo = (T) iter.next();
            mapper.insert(mo);
            numers ++;
        }
        return coll.size()==numers? true:false;
    }

    @Transactional
    public void batchSave(List list) {
        mapper.batchSave(list);
    }

    /**
     * 获取缓存键值
     */
    public String getCacheKey(Object id) {
        String cacheName = null;
        CacheConfig cacheConfig = getClass().getAnnotation(CacheConfig.class);
        if (cacheConfig == null || cacheConfig.cacheNames() == null || cacheConfig.cacheNames().length < 1) {
            cacheName = getClass().getName();
        } else {
            cacheName = cacheConfig.cacheNames()[0];
        }
        return new StringBuilder(Constants.CACHE_NAMESPACE).append(cacheName).append(":").append(id).toString();
    }

    /**
     * 直接从数据库中查询所有数据
     * @param params
     * @return
     */
    public List<T> selectList(Map<String, Object> params) {
        return mapper.selectAll(params);
    }

    public T selectById(String id) {
        try {
            String key = getCacheKey(id);
            T record = (T) JedisUtil.get(key);
            if (record == null) {
                record = mapper.selectByPrimaryKey(id);
                JedisUtil.set(key, record);
            }
            return record;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 查询并返回分页数据，不使用redis，直接从数据库中查询。
     * @param params
     * @return
     */
    public Pageable<T> selectPage(Map<String, Object> params) {
        startPage(params);
        Pageable<T> page = new Pageable(mapper.selectAll(params));
        return page;
    }

    /**
     * 查询并返回分页数据，不使用redis，直接从数据库中查询。
     * @param pageable
     * @return
     */
    public Pageable<T> selectPage(Pageable pageable) {
        if(pageable == null)
            pageable = new Pageable();
        PageHelper.startPage(pageable);

        Map params = new HashMap();
        buildWhere(params, pageable);
        buildOrderBy(params, pageable);

        Pageable<T> page = new Pageable(mapper.selectAll(params));
        return page;
    }

    public T update(T record) {
        try {
            record.setEnable(true);
            record.setUpdateTime(new Date());
            if (record.getId() == null || StringUtils.isBlank(record.getId().toString())) {
                String key = record.getClass().getSimpleName();
                //创建主键
                record.setId(createId(key));
                record.setCreateTime(new Date());
                mapper.insert(record);
            } else {
                mapper.updateByPrimaryKey(record);
            }
            JedisUtil.set(getCacheKey(record.getId()), record);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return record;
    }

    public void deleteById(String id) {
        deleteById(id, WebUtil.getCurrentUserId());
    }

    public void deleteById(String id, String userId) {
        try {
            T record = selectById(id);
            record.setEnable(false);
            record.setUpdateTime(new Date());
            record.setUpdateBy(userId);
            mapper.updateByPrimaryKey(record);
            JedisUtil.set(getCacheKey(id), record);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void delete(T record) {
        try {
            mapper.updateByPrimaryKey(record);
            JedisUtil.set(getCacheKey(record.getId()), record);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public void setMapper(BaseMapper<T> mapper) {
        this.mapper = mapper;
    }

    public BaseMapper getMapper(){
        return mapper;
    }

    public void printIsProxy() {
        //看看mapper是否为代理类
        System.out.println(AopUtils.isAopProxy(mapper));
        System.out.println(AopUtils.isCglibProxy(mapper));
        System.out.println(AopUtils.isJdkDynamicProxy(mapper));
    }

    protected void buildWhere(Map parameter, Pageable pageable) {
        if (pageable == null)
            return;
        Filter filter = null;
        if (pageable.getFilters() != null) {
            Iterator iter = pageable.getFilters().iterator();
            while (iter.hasNext()) {
                filter = (Filter) iter.next();
                if (filter == null || StringUtils.isEmpty(filter.getProperty()))
                    continue;
                if(filter.getValue() instanceof Enum)
                    parameter.put(filter.getProperty(), ((Enum)filter.getValue()).ordinal());
                else
                    parameter.put(filter.getProperty(), filter.getValue());
            }
        }

    }

    protected void buildOrderBy(Map parameter, Pageable pageable) {
        if (pageable == null)
            return;
        String order = " ORDER BY ";
        if (StringUtils.isNotEmpty(pageable.getOrderProperty()) && pageable.getOrderDirection() != null) {
            if (pageable.getOrderDirection() == "asc")
                parameter.put("orderBy", order + pageable.getOrderProperty() + " asc");
            else if (pageable.getOrderDirection() == "desc")
                parameter.put("orderBy", order + pageable.getOrderProperty() + " desc");
        }
    }

    /**
     * 启动分页查询
     */
    protected void startPage(Map<String, Object> params) {
        if (DataUtil.isEmpty(params.get("pageNum"))) {
            params.put("pageNum", 1);
        }
        if (DataUtil.isEmpty(params.get("pageSize"))) {
            params.put("pageSize", 10);
        }
        if (DataUtil.isEmpty(params.get("orderBy"))) {
            params.put("orderBy", " id desc");
        }
        PageHelper.startPage(params);
    }

}
